import * as THREE from 'three';
import { LineSegments2 } from 'three/examples/jsm/lines/LineSegments2'
import { Line2 } from 'three/examples/jsm/lines/Line2'
import { LineGeometry } from 'three/examples/jsm/lines/LineGeometry'
import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial'
import Utils from '../class/Utils'
import Experience from '../class/Experience';

class CreateLine {
    color = 0x54ccfc;
    lineWidth = 1.5;

    constructor(pointArr) {
        this.experience = new Experience();
        const geometry = new LineGeometry(); //创建一个Buffer类型几何体对象
        geometry.setPositions(pointArr);
        const material = new LineMaterial({
            linewidth: this.lineWidth,
            color: this.color,
        })
        material.resolution.set(this.experience.sizes.width, this.experience.sizes.height);
        const line = new Line2(geometry, material)
        return line
    }
}


/**
 * item 线条整理之后的对象
 */
class CreateNormalLine {
    constructor(item) {
        this.experience = new Experience();
        const start = new THREE.Vector3(item.start[0], item.start[1], 0); //起点
        const end = new THREE.Vector3(item.end[0], item.end[1], 0); //终点
        const middle = new THREE.Vector3(0, 0, 0);
        middle.add(start).add(end).divideScalar(2);
        const L = start.clone().sub(end).length();//地图上两点之间距离
        const randomHeight = 0.2 * Math.random() + 0.1;
        const H = L * randomHeight; //轨迹线高度，注意考虑两点距离来设置，弧线高度和两点之间距离正相关
        middle.z += H;

        const offset = L * randomHeight
        if (item.start[0] > item.end[0] && item.start[0] > item.end[0]) {
            middle.x -= offset;
            // middle.y += offset;
        } 
        if (item.start[0] < item.end[0] && item.start[0] < item.end[0]) {
            middle.x += offset;
            // middle.y -= offset;
        } 

        // middle.x += Math.random() * 0.04 - 0.02
        // middle.y += Math.random() * 0.01 - 0.02


        const curve = new THREE.CatmullRomCurve3([
            start,
            middle,
            end,
        ]);
        const points = curve.getSpacedPoints(100); //分段数100，返回101个顶点
        const newPoints = Utils.vector3ArrToNormal(points)
        const geometry = new LineGeometry(); //创建一个Buffer类型几何体对象
        geometry.setPositions(newPoints);
        const material = new LineMaterial({
            color: item.color,
            linewidth: 2.0,
        });
        material.resolution.set(this.experience.sizes.width, this.experience.sizes.height);
        //线条模型对象
        const line = new Line2(geometry, material);
        //注意考虑地图拉伸高度
        // line.position.z = 0.12;
        line.points = points;
        line.includes = item.includes;
        line.color = item.color;
        return line;
    }
}

// 生成飞线
class CreateFly {
    size = 0.006
    // 飞线相对父级线条的起点
    index = 0;

    // 飞线截取父级点位数量 (飞线长度)
    number = 20

    // 飞线用多少个点组成
    divider = 100;

    //Points 父级线条的点位数组
    constructor(points, color, includes) {
        // 截取一飞线
        const list = points.slice(this.index, this.index + this.number);

        // 生成CatmullRomCurve3型飞线
        const curve = new THREE.CatmullRomCurve3(list, false);

        // 获取飞线切分之后的点
        const points2 = curve.getPoints(this.divider);

        // 缓冲区对象
        const geometry = new THREE.BufferGeometry();
        geometry.setFromPoints(points2);

        const percentArr = []; //attributes.percent的数据
        for (let i = 0; i < points2.length; i++) {
            percentArr.push(i / points2.length);
        }

        const percentAttribue = new THREE.BufferAttribute(new Float32Array(percentArr), 1);
        geometry.attributes.percent = percentAttribue;

        // 批量计算所有顶点颜色数据
        const colorArr = [];
        for (let i = 0; i < points2.length; i++) {
            let color1 = new THREE.Color(color); //轨迹线颜色
            let color2 = new THREE.Color(color); 
            let color3 = color1.lerp(color2, i / points2.length)
            colorArr.push(color3.r, color3.g, color3.b);
        }

        // 设置几何体顶点颜色数据
        geometry.attributes.color = new THREE.BufferAttribute(new Float32Array(colorArr), 3);

        // 点模型渲染几何体每个顶点
        const PointsMaterial = new THREE.PointsMaterial({
            // color: 0xffff00,
            size: this.size, //点大小
            vertexColors: true, //使用顶点颜色渲染
        });

        PointsMaterial.onBeforeCompile = (shader) => {
            // 顶点着色器中声明一个attribute变量:百分比
            shader.vertexShader = shader.vertexShader.replace(
                'void main() {',
                [
                    'attribute float percent;', //顶点大小百分比变量，控制点渲染大小
                    'void main() {',
                ].join('\n') // .join()把数组元素合成字符串
            );
            // 调整点渲染大小计算方式
            shader.vertexShader = shader.vertexShader.replace(
                'gl_PointSize = size;',
                [
                    'gl_PointSize = percent * size;',
                ].join('\n') // .join()把数组元素合成字符串
            );
        };


        const flyPoints = new THREE.Points(geometry, PointsMaterial);
        // 用于循环渲染所有飞线
        flyPoints.color = color; // 颜色
        // flyPoints.includes = includes; // 属于哪两个站点
        flyPoints.index = this.index //每条飞线的起点
        flyPoints.number = this.number //每条飞线长度
        flyPoints.divider = this.divider //每条飞线拆分的点
        flyPoints.indexMax = points.length - this.number // 每条飞线最多能跑的点数 超过归零循环
        flyPoints.points = points //每条飞线途径的路径点
        return flyPoints

    }
}

export { CreateLine, CreateNormalLine, CreateFly }
